#ifndef __MY_CONFIG__
#define __MY_CONFIG__

#include <mutex>
#include "util.hpp"

namespace cloud
{
#define CONFIG_FILE "./cloud.conf" // 配置文件路径
    // 这里使用懒汉的单例模式，定义一个静态的Config类指针，
    // 之后在第一次请求单例实例时才创建，延时加载，所以在多线程情况下存在线程安全问题
    class Config
    {
    private:
        Config()
        {
            ReadConfigFile();
        }
        static Config *_instance; // 静态指针属于Config这个类，指向唯一的实例对象
        static std::mutex _mutex; // 静态锁，对Config类来说是一把全局的锁，以确保在任何时候只有一个线程可以访问_instance
    private:
        int _hot_time;
        int _server_port;
        std::string _server_ip;
        std::string _download_prefix; // 下载请求前缀
        std::string _packfile_suffix; // 压缩文件后缀
        std::string _pack_dir;        // 非热点文件压缩文件夹
        std::string _back_dir;        // 热点文件文件夹
        std::string _backup_file;     // 备份文件信息

        bool ReadConfigFile() // 解析配置文件
        {
            FileUtil fu(CONFIG_FILE);
            std::string body;
            if (fu.GetContent(&body) == false)
            {
                std::cout << "load config file failed!\n";
                return false;
            }
            Json::Value root;
            if (JsonUtil::UnSerialize(body, &root) == false)
            {
                std::cout << "parse config file failed!\n";
                return false;
            }
            _hot_time = root["hot_time"].asInt();
            _server_port = root["server_port"].asInt();
            _server_ip = root["server_ip"].asString();
            _download_prefix = root["download_prefix"].asString();
            _packfile_suffix = root["packfile_suffix"].asString();
            _pack_dir = root["pack_dir"].asString();
            _back_dir = root["back_dir"].asString();
            _backup_file = root["backup_file"].asString();
            return true;
        }

    public:
        static Config *GetInstance()
        {
            if (_instance == nullptr) // 当单例对象未被创建时，才能申请锁，减少锁的竞争
            {
                _mutex.lock();
                if (_instance == nullptr) // 因为可能存在第一次判断后，还未申请锁就发生线程调度，让另一线程完成了对象的创建，
                {                         // 再切换到该线程后，该线程已经完成第一次判断，直接申请锁再次创建对象的情况，双重检查

                    _instance = new Config();
                }
                _mutex.unlock();
            }
            return _instance;
        }

        // 获取相应配置数据
        int GetHotTime()
        {
            return _hot_time;
        }

        int GetServerPort()
        {
            return _server_port;
        }

        std::string GetServerIp()
        {
            return _server_ip;
        }

        std::string GetDownloadPrefix()
        {
            return _download_prefix;
        }

        std::string GetPackFileSuffix()
        {
            return _packfile_suffix;
        }

        std::string GetPackDir()
        {
            return _pack_dir;
        }

        std::string GetBackDir()
        {
            return _back_dir;
        }

        std::string GetBackupFile()
        {
            return _backup_file;
        }
    };

    Config *Config::_instance = nullptr;
    std::mutex Config::_mutex; // 调用默认构造完成初始化
}

#endif